package com.mantou.mantouaiagent.controller;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.mantou.mantouaiagent.agent.YuManus;
import com.mantou.mantouaiagent.app.LoveApp;
import com.mantou.mantouaiagent.config.chatmemory.RedisChatMemory;
import com.mantou.mantouaiagent.entities.History;
import com.mantou.mantouaiagent.entities.MessageVo;
import com.mantou.mantouaiagent.entities.dto.ChatDto;
import com.mantou.mantouaiagent.entities.vo.UserVo;
import com.mantou.mantouaiagent.exp.BusinessException;
import com.mantou.mantouaiagent.mapper.HistoryMapper;
import com.mantou.mantouaiagent.resp.ResultData;
import com.mantou.mantouaiagent.resp.ReturnCodeEnum;
import com.mantou.mantouaiagent.service.AiService;
import com.mantou.mantouaiagent.service.HistoryService;
import com.mantou.mantouaiagent.util.IpUtil;
import com.mantou.mantouaiagent.util.SpringSecutiryUtil;
import com.mantou.mantouaiagent.util.ThreadLocalUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.tool.ToolCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RequestMapping("/ai")
@RestController
@Slf4j
public class LoveController {

    @Resource
    private RedisTemplate<String,String> stringRedisTemplate;

    @Resource
    private LoveApp loveApp;

    @Resource
    private HistoryMapper historyMapper;


    @GetMapping("doChat")
    public String doChat(String message, String chatId) {
        return loveApp.doChat(message, chatId);
    }

    @GetMapping(value = "doStream", produces = "text/html;charset=UTF-8")
    public Flux<String> doStream(String message, String chatId) {
        return loveApp.doChatStream(message, chatId);
    }

//    @GetMapping(value = "/love_app/chat/sse")
//    public Flux<ServerSentEvent<String>> doChatWithLoveAppSSE(String message, String chatId) {
//        return loveApp.doChatWithLoveApp(message, chatId)
//                .map(chunk -> ServerSentEvent.<String>builder()
//                        .data(chunk)
//                        .build());
//    }

    @Resource
    private AiService aiService;

    @GetMapping(value = "/love_app/chat/sse/emitter" ,  produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter doChatWithLoveAppSseEmitter(ChatDto userDto, HttpServletRequest request) throws IOException {
        String uid = stringRedisTemplate.opsForValue().get("userId:" + userDto.getUid().toString());
        String chatId = userDto.getChatId();
        String message = userDto.getMessage();

        if (StringUtils.isEmpty( uid)) {
            throw new BusinessException(ReturnCodeEnum.RC403.getCode(),ReturnCodeEnum.RC403.getMessage());
        }
        ThreadLocalUtil.setUserId(Integer.parseInt(uid));
        History history = new History();

        //使用分布式锁存入chatId 用于用户第一次生成会话产生标题
        Boolean titleFlag = stringRedisTemplate.opsForValue().setIfAbsent("userId:"+uid + ":message", message);
        createTitle(userDto, titleFlag, history, chatId, uid);


        SseEmitter sseEmitter = new SseEmitter(180000L);//三分钟超时
        //续期
        stringRedisTemplate.expire("userId:" + userDto.getUid().toString(), 60, TimeUnit.MINUTES);
        //根据ip 限定次数
        String ipAddress = "ip:"+ IpUtil.getIpAddress(request);
        String count = stringRedisTemplate.opsForValue().get(ipAddress);
        //经费有限 限制每日访问次数
        if(!StringUtils.isEmpty(count)&&Long.parseLong(count)>20){
            sseEmitter.send( "您已超过请求最大次数限制,请明日再来");
            return sseEmitter;
//            throw new BusinessException(ReturnCodeEnum.RC998.getCode(),ReturnCodeEnum.RC998.getMessage());
        }else {
            stringRedisTemplate.opsForValue().increment(ipAddress);
        }

        //获取Flux数据流并订阅
        loveApp.doChatWithLoveApp(userDto)
                .subscribe(chunk -> {
                            try {
                                log.info( "发送数据：" + chunk);
                                sseEmitter.send(chunk);
                            } catch (IOException e) {
                                sseEmitter.completeWithError(e);
                            }
                        },
                        sseEmitter::completeWithError, sseEmitter::complete
                );
        return sseEmitter;
    }

    /**
     * 异步生成标题 提高运行速度
     * @param userDto
     * @param titleFlag
     * @param history
     * @param chatId
     * @param uid
     */

    @Async
    public void createTitle(ChatDto userDto, Boolean titleFlag, History history, String chatId, String uid) {
        if(Boolean.TRUE.equals(titleFlag)){
            String title = aiService.doChatGetTitle(userDto);
            history.setTitle(title);
            //创建历史记录
            History historyFlag = historyMapper.selectOne(new LambdaQueryWrapper<History>().eq(History::getChatId, chatId));
            if(ObjectUtil.isEmpty(historyFlag)){
                history.setUserId(uid);
                history.setChatId(chatId);
                history.setStatus(1);
                historyMapper.insert(history);
            }
        }
    }


    @Resource
    private ToolCallback[] allTools;

    @Resource
    private ChatModel dashscopeChatModel;

    @Resource
    private RedisChatMemory redisChatMemory;



    /**
     * 流式调用 Manus 超级智能体
     *
     * @param message
     * @return
     */
    @GetMapping(value = "/manus/chat",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter doChatWithManus(String message) {
        log.info("收到SSE请求: {}", message);
        YuManus yuManus = new YuManus(allTools, dashscopeChatModel);
        return yuManus.runStream2(message);
    }

    @PostMapping ("/create")
    public  UserVo create() {
        UserVo userVo = new UserVo();
        Integer uid = SpringSecutiryUtil.getCurrentUser().getUid();
        //开启新会话后删除上一次用户的chatId缓存
        stringRedisTemplate.delete( "userId:"+uid + ":message");

        String chatId = UUID.randomUUID().toString();
        userVo.setChatId(chatId);
        userVo.setId(uid);
        stringRedisTemplate.opsForValue().set("userId:"+ uid,uid.toString(),60, TimeUnit.MINUTES);
        return userVo;
    }

    @PostMapping("/getChatMemoryList")
    public ResultData<List<History>> getList(@RequestBody ChatDto chatDto){
        Integer uid = chatDto.getUid();
        Integer status = chatDto.getStatus();
        if (uid==null) {
            throw new BusinessException("500", "用户ID不能为空");
        }
        List<History> histories = historyMapper.selectList(new LambdaQueryWrapper<History>()
                .eq(History::getUserId, uid)
                .eq(History::getStatus,status)
                .orderByDesc(History::getCreatetime)
                .last("limit 10"));
        return ResultData.success(histories);
    }

    @PostMapping("/getChatMemory")
    public ResultData<MessageVo> getChatMemory(@RequestBody ChatDto chatDto){
        Integer uid = chatDto.getUid();
        String chatId = chatDto.getChatId();
        if (chatId==null) {
            throw new BusinessException("500", "chatId不能为空");
        }
        if (uid==null) {
            throw new BusinessException("500", "用户ID不能为空");
        }

        History history = historyMapper.selectOne(new LambdaQueryWrapper<History>().eq(History::getChatId, chatId).eq(History::getUserId, uid));
        if (ObjectUtil.isEmpty(history)){
            throw new BusinessException("500", "用户没有此会话");
        }
        List<Message> messages = redisChatMemory.get(chatId, 10);
        log.info("messages:{}",messages);
        return ResultData.success(new MessageVo(history.getTitle(),  messages));
    }

    @PostMapping("/deleteChatMemory")
    public ResultData deleteChatMemory(@RequestBody ChatDto chatDto){
        log.info("deleteChatMemory:{}",chatDto);
        Integer uid = chatDto.getUid();
        String chatId = chatDto.getChatId();
        if (StringUtils.isEmpty(chatId)) {
            throw new BusinessException("500", "chatId不能为空");
        }
        if (uid==null) {
            throw new BusinessException("500", "用户ID不能为空");
        }
        int delete = historyMapper.delete(new LambdaQueryWrapper<History>().eq(History::getChatId, chatId).eq(History::getUserId, uid));
        if (delete>0) {
            redisChatMemory.clear(chatId);
        }
        log.info("delete:{}",delete==1?"删除："+chatId+"成功":"删除："+chatId+"失败");

        return ResultData.success(delete==1?"删除成功":"删除失败");
    }

    @PostMapping("/updateChatMemoryTitle")
    public ResultData updateChatMemoryTitle(@RequestBody ChatDto chatDto){
        log.info("updateChatMemoryTitle:{}",chatDto);
        Integer uid = chatDto.getUid();
        String chatId = chatDto.getChatId();
        String title = chatDto.getTitle();
        if (StringUtils.isEmpty(title)) {
            throw new BusinessException("500", "chatId不能为空");
        }
        if (uid==null) {
            throw new BusinessException("500", "用户ID不能为空");
        }
        int update = historyMapper.update(new LambdaUpdateWrapper<History>().eq(History::getChatId, chatId).eq(History::getUserId, uid).set(History::getTitle, title).set(History::getCreatetime, new Date()));
        log.info("update:{}",update==1?"修改："+chatId+"成功":"修改："+chatId+"失败");
        return ResultData.success(update==1?"修改成功":"修改失败");
    }
}
